#ifndef __SELECT_SERVER_HPP__
#define __SELECT_SERVER_HPP__

#include <iostream>
#include <string>
#include <sys/select.h>
#include <unistd.h>
#include "Log.hpp"
#include "Sock.hpp"

#define FD_NONE -1

class SelectServer
{
private:
    static const int g_nfds = 100;

public:
    SelectServer(uint16_t port = 8080, int nfds = g_nfds)
        : _listenfd(-1), _nfds(nfds), _rfds(new int[_nfds])
    {
        bool ret = _sock.CreateServer(8080);
        if (ret == false)
            exit(1);
        _listenfd = _sock.Fd();
        for (int i = 0; i < _nfds; i++)
        {
            _rfds[i] = FD_NONE;
        }
        _rfds[0] = _listenfd;
    }

    void Accept()
    {
        uint16_t port = 0;
        std::string ip;
        int sockfd = _sock.Accept(&port, &ip);
        if (sockfd < 0)
        {
            ELOG("server accept failed!!!");
            return;
        }
        int i = 0;
        for (; i < _nfds; i++)
        {
            if(_rfds[i]==FD_NONE) break;
        }
        if(i==_nfds)
        {
            DLOG("_rfds数组满了！！！");
        }
        else
        {
            DLOG("get new link,sockfd:%d port:%d ip:%s",sockfd,port,ip.c_str());
            _rfds[i]=sockfd;
        }
    }

    void Excepter(int sockfd)
    {
        for(int i=0;i<_nfds;i++)
        {
            if(_rfds[i]==sockfd)
            {
                _rfds[i]=FD_NONE;
                close(sockfd);
                break;
            }
        }
    }

    void Recver(int sockfd)
    {
        char buffer[1024];
        bzero(buffer,sizeof(buffer));
        ssize_t s=recv(sockfd,buffer,sizeof(buffer)-1,0);
        if(s>0)
        {
            buffer[s]='\0';
            printf("client# %s\n",buffer);
            std::string messages="hello world#";
            messages+=buffer;
            send(sockfd,messages.c_str(),messages.size(),0);
        }
        else if(s==0)
        {
            DLOG("aside close,me too.....");
            Excepter(sockfd);
        }
        else
        {
            ELOG("server recv failed!!!!");
            Excepter(sockfd);
        }
    }

    void LoopOnce()
    {
        fd_set set;
        FD_ZERO(&set);
        int maxfd = _listenfd;
        for (int i = 0; i < _nfds; i++)
        {
            if (_rfds[i] == FD_NONE)
                continue;
            FD_SET(_rfds[i], &set);
            if (_rfds[i] > maxfd)
                maxfd = _rfds[i];
        }

        int n = select(maxfd + 1, &set, nullptr, nullptr, nullptr);
        for (int i = 0; i < _nfds; i++)
        {
            if (_rfds[i] == FD_NONE)
                continue;
            if (FD_ISSET(_rfds[i], &set))
            {
                if (_rfds[i] == _listenfd)
                {
                    Accept();
                }
                else
                {
                    Recver(_rfds[i]);
                }
            }
        }
    }

    void Start()
    {
        while (true)
        {
            LoopOnce();
        }
    }

private:
    int _listenfd;
    Sock _sock;
    int _nfds;
    int *_rfds;
};

#endif